
bl_info = {
    "name": "Import OSSL LLM File",
    "author": "Tom Ernst",
    "version": (1, 0, 0),
    "blender": (2, 93, 0),
    "location": "Topbar > OSSL Menu > Import OSSL LLM File",
    "description": "Import OSSL Old Mesh File",
    "warning": "",
    "doc_url": "https://rowlplay.net/blender/llmimp.txt",
    "category": "Import-Export",
}

import bpy, os
from math import pi
from struct import unpack
from mathutils import Vector, Matrix, Euler
from ossl import util
import bmesh

class Format_LLM(object):
    def __init__(self, name):
        self.name = name
        self.title = ""
        self.hasWeights = False
        self.hasDetailTexCoords = False
        self.position = Vector((0,0,0))
        self.rotation = Euler((0,0,0), "XYZ")
        self.rotationOrder = 0
        self.scale = Vector((0,0,0))
        self.numVerts = 0
        self.verts = []
        self.norms = []
        self.binorms = []
        self.texCoords = []
        self.weights = []
        self.detailTexCoords = []
        self.numFaces = 0
        self.faces = []
        self.numSkinJoints = 0
        self.skinJoints = []
        self.numMorphs = 0
        self.morphs = []
        self.numRemaps = 0
        self.remaps = []
        
        self.male_morph_indices = []
        
        self.file_import(util.path("resources\\avatar_" + self.name + ".llm"))
    
    def read_string(self, len):
        ba = self.infile.read(len)
        for i in range(0, len):
            if (ba[i] == 0): break
        return bytes(ba[0:i]).decode('UTF-8')

    def file_import(self, filepath):
        print("importing from", filepath)
        self.infile = open(filepath, 'rb')
        try:
            self.title = self.read_string(24) # bytes(ba[0:i]).decode('UTF-8')
            print("\ttitle: %s" % self.title)
            
            self.hasWeights = (self.infile.read(1)[0] != 0)
            print("\thasWeights: %i" % self.hasWeights)

            self.hasDetailTexCoords = (self.infile.read(1)[0] != 0)
            print("\thasDetailTexCoords: %i" % self.hasDetailTexCoords)
            
            self.position = Vector(unpack("fff", self.infile.read(12)))
            print("\tposition:", self.position)

            self.rotation = Euler(unpack("fff", self.infile.read(12)), "XYZ")
            self.rotationOrder = self.infile.read(1)[0]
            if (self.rotationOrder != 0): self.rotation.order = "???"
            print("\trotation:", self.rotation)

            self.scale = Vector(unpack("fff", self.infile.read(12)))
            print("\tscale:", self.scale)

            self.numVerts = unpack("H", self.infile.read(2))[0]
            print("\tnumVertices: %i" % self.numVerts)
            
            for i in range(0, self.numVerts):
                self.verts.append(Vector(unpack("fff", self.infile.read(12))))

            for i in range(0, self.numVerts):
                self.norms.append(Vector(unpack("fff", self.infile.read(12))))

            for i in range(0, self.numVerts):
                self.binorms.append(Vector(unpack("fff", self.infile.read(12))))

            for i in range(0, self.numVerts):
                self.texCoords.append(Vector(unpack("ff", self.infile.read(8))))

            if self.hasDetailTexCoords:
                for i in range(0, self.numVerts):
                    self.detailTexCoords.append(unpack("ff", self.infile.read(8)))
                print("\thas DetailTextCoords")
            else: print("\thas no DetailTextCoords")

            if self.hasWeights:
                mmw = [0]*100
                for i in range(0, self.numVerts):
                    self.weights.append(unpack("f", self.infile.read(4))[0])
                    mw = (int)(self.weights[-1])
                    mmw[mw] += 1
                print("\thas Weights")
                for i in range(0, len(mmw)):
                    if (mmw[i] != 0): print("\t\t#weights for %i: %i" % (i, mmw[i]))
            else: print("\thas no Weights")

            self.numFaces = unpack("H", self.infile.read(2))[0]
            print("\tnumFaces: %i" % self.numFaces)
            
            for i in range(0, self.numFaces):
                self.faces.append(unpack("HHH", self.infile.read(6)))

            if self.hasWeights:
                self.numSkinJoints = unpack("H", self.infile.read(2))[0]
                print("\tnumSkinJoints: %i" % self.numSkinJoints)
            
                for i in range(0, self.numSkinJoints):
                    self.skinJoints.append(self.read_string(64))
                    print("\t\tskinJoint(%i): %s" % (i, self.skinJoints[-1]))

            print("\tMorphs")
            while True:
                s = self.read_string(64)
                if s == "End Morphs": break

                nV = unpack("i", self.infile.read(4))[0]
                print("\t\t%s – numVerts: %i" % (s, nV))

                v = []
                for i in range(0, nV):
                    vix = unpack("i", self.infile.read(4))[0]
                    co = Vector(unpack("fff", self.infile.read(12)))
                    nm = Vector(unpack("fff", self.infile.read(12)))
                    bi = Vector(unpack("fff", self.infile.read(12)))
                    tx = Vector(unpack("ff", self.infile.read(8)))
                    v.append((vix, co, nm, bi, tx))
                    # vertex-index, location, normal, binormal, texco
            
                if s.lower().find("male") >= 0: self.male_morph_indices.append(len(self.morphs))
                self.morphs.append((s, v))
            
            dummy = self.infile.read(4)
            if (len(dummy) != 4): print("EOF reached, no remaps")
            else:
                self.numRemaps = unpack("i", dummy)[0]
            
                for i in range(0, self.numRemaps):
                    self.remaps.append(unpack("ii", self.infile.read(8)))
                
                print("\tlen(remaps): %i" % len(self.remaps));
                dummy = self.infile.read(1)

            if (len(dummy) == 0): print("EOF reached")
            else: print("EOF not reached")

        finally:
            self.infile.close()

        print("LLM Imported")
        

def register():
    print("registering: OSSL Format LLM")
    print("registered: OSSL Format LLM")

def unregister():
    print("unregistering: OSSL Format LLM")
    print("unregistered: OSSL Format LLM")

import ossl.util as util

if __name__ == "__main__":
    util.reset_addon()
